//
//  UnitList.m
//  MapEdit
//
//  Created by Steven Canfield on 25/06/07.
//  Copyright 2007 __MyCompanyName__. All rights reserved.
//

#import "UnitList.h"

float distance( NSPoint a, NSPoint b) {
	float x_distance = a.x - b.x;
	float y_distance = a.y - b.y;
	return sqrt( x_distance * x_distance + y_distance * y_distance ); 
}

void printUnitInfo( chk_unit_t * unit, int unitCount ) {
	int unitIndex;
	printf("\n");
	for( unitIndex = 0; unitIndex < unitCount; unitIndex++ ) {
			u_int8_t pieces[4];
			u_int16_t shorts[2];
			memcpy( &pieces , &unit[unitIndex].identifier , sizeof( u_int32_t ));
			memcpy( &shorts , &unit[unitIndex].identifier , sizeof( u_int32_t ));
		printf( ":%i:(%i %i %i %i)", unit[ unitIndex].identifier, pieces[3], pieces[2], pieces[1], pieces[0]);
		printf( ":%i - %i", shorts[1], shorts[2] );
		printf( ":%i", unit[ unitIndex].owner);
		printf( ":%i", unit[ unitIndex].x);
		printf( ":%i", unit[ unitIndex].y);
		printf( ":%i", unit[ unitIndex].type);
		printf( ":%i", unit[ unitIndex].property);
		printf( ":%i", unit[ unitIndex].unknown0);
		printf( ":%i", unit[ unitIndex].property_valid);
		printf( ":%i", unit[ unitIndex].stat_valid);
		printf( ":%i", unit[ unitIndex].health);
		printf( ":%i", unit[ unitIndex].shield);
		printf( ":%i", unit[ unitIndex].energy);
		printf( ":%i", unit[ unitIndex].resource);
		printf( ":%i\n", unit[ unitIndex].hanger_size);

//		printf("===================  %03i  =======================\n", unitIndex);
//		printf( "identifier     = %i\n", unit[ unitIndex].identifier);
/*
		printf( "%i:(%i %i %i %i)\t", unit[ unitIndex].identifier, pieces[3], pieces[2], pieces[1], pieces[0]);
		printf( ":%i", unit[ unitIndex].owner);
		printf( ":\t", unit[ unitIndex].x);
		printf( "y = %i\t", unit[ unitIndex].y);
		printf( "type = %i\t", unit[ unitIndex].type);
		printf( "property       = %i\n", unit[ unitIndex].property);
		printf( "unknown0       = %i\n", unit[ unitIndex].unknown0);
		printf( "property_valid = %i\n", unit[ unitIndex].property_valid);
		printf( "stat_valid     = %i\n", unit[ unitIndex].stat_valid);
		printf( "owner          = %i\n", unit[ unitIndex].owner);
		printf( "health         = %i\n", unit[ unitIndex].health);
		printf( "shield         = %i\n", unit[ unitIndex].shield);
		printf( "energy         = %i\n", unit[ unitIndex].energy);
		printf( " resource      = %i\n", unit[ unitIndex].resource);
		printf( "hanger_size    = %i\n", unit[ unitIndex].hanger_size);
		printf( "property       = %i\n", unit[ unitIndex].property);
		printf( "unused1        = %i\n", unit[ unitIndex].unused1);
		printf( "unused2        = %i\n", unit[ unitIndex].unused2);
		printf( "unused3        = %i\n", unit[ unitIndex].unused3);
		printf( "unused4        = %i\n", unit[ unitIndex].unused4);
		printf( "unused5        = %i\n", unit[ unitIndex].unused5);
		printf( "unused6        = %i\n", unit[ unitIndex].unused6);
		printf( "unused7        = %i\n", unit[ unitIndex].unused7);
		printf( "unused8        = %i\n", unit[ unitIndex].unused8);
		*/
	}
}

@implementation UnitList
- (id)initWithData:(NSData *)data {
	self = [super init];
	if( self ) {
		units = malloc( [data length] );
		[data getBytes:units length:[data length]];
		unitCount = [data length] / sizeof( chk_unit_t );
		unitArray = [[NSMutableArray alloc] init];
		[self sortUnitList];
		
		int unitIndex;
		for( unitIndex = 0; unitIndex < unitCount; unitIndex++ ) {
			units[ unitIndex ].identifier = NSSwapLittleIntToHost( units[unitIndex].identifier );
			units[ unitIndex ].x = NSSwapLittleShortToHost( units[unitIndex].x );
			units[ unitIndex ].y = NSSwapLittleShortToHost( units[unitIndex].y );
			units[ unitIndex ].type = NSSwapLittleShortToHost( units[unitIndex].type );
			units[ unitIndex ].unknown0 = NSSwapLittleShortToHost( units[unitIndex].unknown0 );
			units[ unitIndex ].property_valid = NSSwapLittleShortToHost( units[unitIndex].property_valid );
			units[ unitIndex ].stat_valid = NSSwapLittleShortToHost( units[unitIndex].stat_valid );
			units[ unitIndex].resource = NSSwapLittleIntToHost( units[ unitIndex ].resource );
			units[ unitIndex ].hanger_size = NSSwapLittleShortToHost( units[unitIndex].hanger_size );
			units[ unitIndex ].property = NSSwapLittleShortToHost( units[unitIndex].property );
			
			if( units[ unitIndex ].identifier  > _nextIdentifier ) {
				_nextIdentifier = units[ unitIndex ].identifier;
			}
			
			
			[unitArray addObject:@"EMPTY"];
		}
		
		_nextIdentifier += 104;
		//_nextIdentifier = 54763964;
		
		printUnitInfo( units, unitCount );
		
	}
	
	return self;
}

- (NSData *)serializedUnitList {
	NSMutableData * data = [[NSMutableData alloc] init];
	[data appendSectionNamed:"UNIT" withBytes:units length:unitCount * sizeof( chk_unit_t )];
	return data;
}

- (NSString *)description {
	return [NSString stringWithFormat:@"UnitList contains %i units", unitCount];
}

- (void)swapUnitAtIndex:(int)index withUnit:(int)otherIndex {
	chk_unit_t swap;
	memcpy( &swap , &units[index] , sizeof( chk_unit_t ));
	memcpy( &units[index], &units[otherIndex], sizeof(chk_unit_t ));
	memcpy( &units[otherIndex], &swap, sizeof( chk_unit_t ));
}

- (BOOL)compare:(int)index with:(int)compareIndex {
	chk_unit_t unit1 = units[index];
	chk_unit_t unit2 = units[compareIndex];
	if( unit1.identifier < unit2.identifier ) {
		return NO;
	}
	return YES;
}

- (void)sortUnitList {
	int i, j;
	for( i = 0; i < unitCount; i++ ) {
		for( j = 0; j < unitCount; j++ ) {
			if( [self compare:i with:j] == NO ) {
				[self swapUnitAtIndex:i withUnit:j];
			}
		}
	}
}

- (int)unitCount {
	return unitCount;
}

- (Unit *)unitAtIndex:(int)index {
	if( index < 0 && index > unitCount ) {
		DebugLog(@"unit index (%i) beyound bounds (%i)", index, unitCount );
	}
	if( [[unitArray objectAtIndex:index] isEqual: @"EMPTY"] ) {
		Unit * u = [Unit unitWithData:&units[index]];
		[unitArray replaceObjectAtIndex:index withObject:u];
	}
	return [unitArray objectAtIndex: index ];//[Unit unitWithData:&units[index]];
}

- (void)addUnitAtX:(int)x Y:(int)y type:(int)type owner:(int)owner{
	/* Reallocate Larger Size */
	chk_unit_t * newUnits = realloc( units, sizeof( chk_unit_t) * (unitCount + 1));
	if( newUnits == NULL ) {
		/* Allocation Failed */
		abort();
	}
	
	//NSLog(@"Moved units from %x to %x", units, newUnits );
	/* Point units to new space */
	units = newUnits;
	
	/* Create New Unit */
	chk_unit_t unit;
	memset( &unit, 0, sizeof (chk_unit_t ));
	unit.x = x;
	unit.y = y;
	unit.type = type;
	unit.owner = owner;
	unit.health = 100;
	unit.stat_valid ^= 1;
	unit.stat_valid ^= 2;
	unit.property_valid = 24;
	unit.identifier = _nextIdentifier;
	_nextIdentifier += 16;
	
	//NSLog(@"Created New Unit with identifier %i", _nextIdentifier -  1);
	
	/* Copy unit across */
	memcpy( &units[ unitCount ] , &unit , sizeof( chk_unit_t ));
	
	/* Resize unit count */
	unitCount++;
	
	printUnitInfo( &units[ unitCount - 1] , 1 );
}

- (int)indexOfClosestUnitToPoint:(NSPoint)point {
	float lowestDistance = 1000000.0f;
	int unitIndex;
	int lowestIndex;
	//NSLog( NSStringFromPoint( point ));
	for( unitIndex = 0; unitIndex < [self unitCount]; unitIndex++ ) {
		float dist = distance( NSMakePoint( units[ unitIndex ].x, units[ unitIndex ].y), point );
		if( dist < lowestDistance ) {
			NSLog( @"New nearest is %@ - (distance is %f)", NSStringFromPoint( NSMakePoint( units[ unitIndex ].x, units[ unitIndex ].y) ), lowestDistance);
			lowestDistance = dist;
			lowestIndex = unitIndex;
		} else {
			NSLog( @"Rejecting %@", NSStringFromPoint( NSMakePoint( units[ unitIndex ].x, units[ unitIndex ].y)  ));
		}
	}
	return lowestIndex;
}

@end
